const jwt = require("jsonwebtoken");
const SECRET_KEY = "xxinfairsn@asin34ai_SRTin";
const Sqlite = require("./sqlite.cjs");
const DB = new Sqlite();
const tableName = "personInfo";
const bcrypt = require("bcrypt");
const webLoginPage = "http://localhost:3000/login";
const loginPage = "/api/login";
const { checkAccount } = "./share.cjs";
let meg;
let ok;

const login = async (user) => {
  let userinfo = {};
  try {
    // 0. check required fields
    if (!(user && user.name && user.password)) {
      throw new Error("invailed parameters!  name or password is empty!");
    }
    // 1.get user info
    const users = await DB.queryTable({
      tableName: tableName + "_data",
      where: "textInput101 = ?",
      params: [user.account],
    });
    //console.log(users);
    if (users.length !== 1) {
      throw new Error("login: account not found or account repeatedly.");
    }
    // 2.compare paassword
    const encrypted = users[0].textInput102;
    console.log(encrypted);
    ok = bcrypt.compareSync(user.password, encrypted);
    //console.log("ok:", ok);
    if (!ok) {
      throw new Error("login: password not match.");
    }
    meg = "login success";
    // attach users info (user dataMap, make data more readable)
    const tableInfo = await DB.queryTable({ tableName: tableName });
    userinfo = DB.tableDataMap(users[0], tableInfo);
  } catch (e) {
    ok = false;
    meg = e;
  } finally {
    DB.close();
    return {
      message: meg,
      ok: ok,
      user: userinfo,
    };
  }
};

const register = async (user) => {
  try {
    console.log(user);
    // 0. check required fields
    if (!(user && user.name && user.password)) {
      throw "invailed parameters!  name or password is empty!";
    }
    // 1. check user's account is valid, here is phone number
    if (!checkAccount(user.account)) {
      throw "account is not vaild!";
    }
    // 2. check user's account is exists?
    const users = await DB.queryTable({
      tableName: tableName + "_data",
      where: "textInput101 = ?",
      params: [user.account],
    });
    // const usersAll = await DB.queryTable({
    //   tableName: "personInfo_data",
    // });
    // //console.log(`usersAll is:`, ...usersAll);
    //console.log(`users is:`, ...users);
    if (users.length > 0) {
      throw "account has exists";
    }
    // 3. create new user
    await DB.insertManyData({
      tableName: tableName + "_data",
      //          name,      account,      password,      identity
      schemas: [
        //ruquired
        "textInput100", //name  ,    true
        "textInput101", //account     true
        "textInput102", //password true
        "numberInput103", //phone
        "select104", //identity
      ],
      data: [
        {
          textInput100: user.name,
          textInput101: user.account,
          textInput102: user.password,
          textInput103: user.phone,
          select104: "user", //this is default normal user
        },
      ],
    });
    meg = `user ${user.name} register succuss.`;
    ok = true;
  } catch (e) {
    console.log(e);
    console.error("register: [failed to register new user.]");
    meg = e;
    ok = false;
  } finally {
    DB.close();
    return {
      message: meg,
      ok: ok,
    };
  }
};
//
const run = async () => {
  const user = {
    name: "h",
    password: "h",
    account: "17112345678",
  };
  // meg = await register(user);
  // console.log(meg);
  //  return;
  meg = await login(user);
  console.log(meg);
};
//run();

const auth = async (req, res, next) => {
  try {
    //1. check path is login?
    const isLoginPage = req.path === loginPage;
    if (isLoginPage) {
      const user = req.body.user;
      //1. login in by password
      const result = await login(user);
      console.log(result);
      if (result.ok) {
        //2. return token
        const token = jwt.sign(result.user, SECRET_KEY, { expiresIn: "10d" });
        res.status(200).json({ token });
        next();
      } else {
        throw result.message;
      }
      //
    } else {
      //console.log("enter try");
      // check token
      const raw = req.headers.authorization;
      const token = String(raw).split(" ")[1];
      if (!token) {
        throw "servers: Unauthorized";
      }
      jwt.verify(token, SECRET_KEY, (err, user) => {
        if (err) {
          throw "serves auth: token auth failed";
        }
        // ok, get user info
        req.user = user;
        next();
      });
    }
  } catch (e) {
    // auth failed, into login page
    console.log(e);
    console.log(req.body);
    res.redirect(webLoginPage);
  }
};

module.exports = {
  auth,
  login,
  register,
};
